
import { toRaw, ref } from 'vue'

import type { Ref } from 'vue'

/**
 * 对象 key 的 类型
 */
export type IStateKey = string | number | symbol

/**
 * 任意一个对象
 */
export type IAnyObject = {[key: IStateKey]: any}

/**
 * 任意一个数组
 */
export type IAnyArray = Array<any>

/**
 * 任意一个函数，返回对象
 */
export type IAnyFunctionObject = () => IAnyObject

/**
 * 任意一个函数，返回数组
 */
export type IAnyFunctionArray = () => IAnyArray

/**
 * 对象或者函数
 */
export type IObjectOrFunction = IAnyObject | IAnyFunctionObject

/**
 * 数组或者函数
 */
export type IArrayOrFunction = IAnyArray | IAnyFunctionArray

/**
 * 对象或者数组
 */
export type IObjectOrArray = IAnyObject | IAnyArray

/**
 * 私有成员的状态
 */
export class UserState {
  #name: Ref<string> // 有响应性
  #department: number // 没有响应性，外面加上 reactive 也不行
  #rules: {
    modules: Array<number | string>
  }

  constructor () {
    this.#name = ref('测试私有成员的响应性')
    this.#department = 18
    this.#rules = {
      modules: []
    }
  }
  
  /**
   * 获取name
   */
  get $name(): string {
    // 需要返回 value，否则 name 会被修改
    return toRaw(this).#name.value
  }

  /**
   * 获取部门
   */
  get department() {
    // 取原型，失去响应性；不取原型，this 指向被改变，无法访问私有成员。
    return toRaw(this).#department
  }

  // 操作状态的函数
  /**
   * 登录，设置状态
   */
  async login() {
    // 实现登录的代码
    toRaw(this).#rules.modules.push(100)
    toRaw(this).#name.value = '登录成功！'
  }

  /**
   * 退出登录
   */
  async signOut() {
    // 实现退出的代码
    toRaw(this).#rules.modules.length = 0
    toRaw(this).#name.value = '没有登录'
  }

  /**
   * 验证权限
   */
  verifyPermissions(modulesId: number | string) {
    return toRaw(this).#rules.modules.includes(modulesId)
  }

}


/**
 * 基础的状态
 */
export class UserState2 {
  name: string
  department: number
  rules: {
    modules: Array<number | string>
  }
  // 初始化
  constructor() {
    this.name = '没有登录'
    this.department = 0
    this.rules = {
      modules: []
    }
  }
  
  // 操作状态的函数
  /**
   * 登录，设置状态
   */
  login() {
    // 实现登录的代码
    this.rules.modules.push(100)
    this.name = '登录成功！'
  }

  /**
   * 退出登录
   */
  signOut() {
    // 实现退出的代码
    this.rules.modules.length = 0
    this.name = '没有登录'
  }

  /**
   * 验证权限
   */
  verifyPermissions(modulesId: number | string) {
    return this.rules.modules.includes(modulesId)
  }

}


